package main

import (
	"fmt"
)

// 观察者模式定义了对象之间的一对多依赖关系，当一个对象的状态发生改变时，所有依赖它的对象都会得到通知并自动更新

// Observer 观察者接口
type Observer interface {
	Update(message string)
	GetName() string
}

// Subject 主题接口
type Subject interface {
	Register(observer Observer)
	Deregister(observer Observer)
	Notify(message string)
}

// ConcreteObserver 具体观察者
type ConcreteObserver struct {
	name string
}

func (co *ConcreteObserver) Update(message string) {
	fmt.Printf("%s received message: %s\n", co.name, message)
}

func (co *ConcreteObserver) GetName() string {
	return co.name
}

// ConcreteSubject 具体主题
type ConcreteSubject struct {
	title     string
	observers []Observer
}

func (cs *ConcreteSubject) Register(observer Observer) {
	cs.observers = append(cs.observers, observer)
	fmt.Printf("observer name:%s register subject title:%s\n", observer.GetName(), cs.title)
}

func (cs *ConcreteSubject) Deregister(observer Observer) {
	for i, obs := range cs.observers {
		if obs == observer {
			cs.observers = append(cs.observers[:i], cs.observers[i+1:]...)
			break
		}
	}
}

func (cs *ConcreteSubject) Notify(message string) {
	for _, observer := range cs.observers {
		observer.Update(message)
	}
}

func main() {
	var subject Subject = &ConcreteSubject{title: "Subject 1"}

	observer1 := &ConcreteObserver{name: "Observer 1"}
	observer2 := &ConcreteObserver{name: "Observer 2"}

	subject.Register(observer1)
	subject.Register(observer2)

	subject.Notify("Hello, observers!")

	subject.Deregister(observer2)

	subject.Notify("New message after deregistration.")
}
